package com.fs.web.base.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fs.common.baseMapper.AttachmentMapper;
import com.fs.common.pojo.Attachment;
import com.fs.common.pojo.User;
import com.fs.web.base.enums.CodeEnum;
import com.fs.web.base.param.SysConstant;
import com.fs.web.base.service.BaseService;
import com.fs.web.base.utils.ApplicationUtils;
import com.fs.web.base.utils.EncodeUtil;
import com.fs.web.base.utils.PageHeper;
import com.fs.web.base.vo.Criteria;
import com.fs.web.base.vo.DataGrid;
import com.fs.web.base.vo.JsonResponse;
import com.fs.web.base.vo.SysPath;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author ACE
 * @desc controller公用方法(慎重修改)
 * @creationTime 2019-03-13 10:39
 * @projectName gps-root
 * @packageName com.fs.base.controller
 */
@Slf4j
@Controller
@RequestMapping("/console")
public class BaseController {
    @Getter @Setter @Value("${layui.upload.path}")
    private String layuiUploadPath;
    @Autowired
    private BaseService baseService;
    @Autowired
    private AttachmentMapper attachmentMapper;

    /**
     * 通用模块首页
     * @param modleName
     * @return
     */
    @GetMapping("{modleName}/index")
    public String index(@PathVariable String modleName, HttpServletRequest req) {
        Map<String, Object> data = ApplicationUtils.getRequestDatas();

        req.setAttribute("modleName", modleName);
        req.setAttribute("className", SysConstant.MODLE_CLASSNAME.get(modleName));

        //传递请求参数到目标页面
        req.setAttribute("data", data);

        return SysPath.BACK_PATH.concat("/"+modleName).concat("/index");
    }

    /**
     * 通用模块预新增
     * @param modleName
     * @return
     */
    @GetMapping("{modleName}/preAdd")
    public String preAdd(@PathVariable String modleName, HttpServletRequest req) {
        req.setAttribute("modleName", modleName);
        req.setAttribute("className", SysConstant.MODLE_CLASSNAME.get(modleName));
        return SysPath.BACK_PATH.concat("/"+modleName).concat("/add");
    }

    /**
     * 通用模块预编辑
     * @param modleName
     * @return
     */
    @GetMapping("{modleName}/preModify")
    public String preModify(@PathVariable String modleName, HttpServletRequest req) {
        req.setAttribute("modleName", modleName);
        req.setAttribute("className", SysConstant.MODLE_CLASSNAME.get(modleName));

        return SysPath.BACK_PATH.concat("/"+modleName).concat("/modify");
    }

    /**
     * 通用模块查看
     * @param modleName
     * @return
     */
    @GetMapping("{modleName}/view")
    public String view(@PathVariable String modleName, HttpServletRequest req) {
        req.setAttribute("modleName", modleName);
        req.setAttribute("className", SysConstant.MODLE_CLASSNAME.get(modleName));

        return SysPath.BACK_PATH.concat("/"+modleName).concat("/view");
    }

    /**
     * 通用模块配置
     * @param modleName
     * @return
     */
    @GetMapping("{modleName}/config")
    public String configGet(@PathVariable String modleName, HttpServletRequest req) {
        req.setAttribute("modleName", modleName);
        req.setAttribute("className", SysConstant.MODLE_CLASSNAME.get(modleName));

        return SysPath.BACK_PATH.concat("/"+modleName).concat("/config");
    }

    /**
     * 通用选择页面
     * @param modleName
     * @return
     */
    @GetMapping("{modleName}/choosebox")
    public String choosebox(@PathVariable String modleName, HttpServletRequest req) {
        req.setAttribute("modleName", modleName);
        req.setAttribute("className", SysConstant.MODLE_CLASSNAME.get(modleName));
        return SysPath.BACK_PATH.concat("/choosebox/"+modleName);
    }

    /**
     * 视频查看页面
     */
    @RequestMapping("/video")
    public String video(HttpServletRequest request){
        Map<String, Object> map = ApplicationUtils.getRequestDatas();
        String id = map.get("id").toString();
        Attachment attachment = attachmentMapper.selectById(id);
        request.setAttribute("url",attachment.getTitle());
        return SysPath.BACK_PATH.concat("/choosebox").concat("/video");
    }

    /**
     * 通用模块分页查询
     * @param className
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("{className}/list")
    public JsonResponse list(@PathVariable String className, HttpServletRequest request) {
        try {
            DataGrid grid = new DataGrid(request);
            Map<String, Object> data = ApplicationUtils.getRequestDatas();
            Object isTree = data.get("isTree");
            if(ApplicationUtils.isSuperAdmin()){
                data.remove("createrId");
            }
            QueryWrapper<Object> wrapper = new Criteria<Object>().addAuto(data);

            //树形
            if (isTree != null) {
                List<Object> list = baseService.findAllWithSort(className, request, wrapper);
                grid = DataGrid.treeBuilder(list,grid);
            }
            //普通表格
            else {
                if(PageHeper.isPage(request)){
                    IPage page = baseService.page(className, request, wrapper);
                    grid = DataGrid.gridBuilder(page);
                }else{
                    List<Object> rows = baseService.findAllWithSort(className, request, wrapper);
                    grid = DataGrid.gridBuilder(rows);
                }
            }
            return JsonResponse.success(grid);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return JsonResponse.error(CodeEnum.EX999);
        }
    }

    /**
     * 通用模块新增
     * @param className
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("{className}/newAdd")
    public JsonResponse newAdd(@PathVariable String className, HttpServletRequest request) {
        try {
            Map<String, Object> map = ApplicationUtils.getRequestDatas();
            Object vo = Class.forName(className).newInstance();
            /*
             * 用户密码特殊处理
             */
            if(vo instanceof User){
                Object pwd = map.get("pwd");
                if(pwd!=null){
                    map.put("pwd", EncodeUtil.getSignAndMD5(pwd.toString()));
                }
            }
            String json = JSON.toJSONString(map);
            vo = JSON.parseObject(json, vo.getClass());
            baseService.beanSpecification(className).insert(vo);
            return JsonResponse.success();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return JsonResponse.error(CodeEnum.EX999);
        }
    }

    /**
     * 通用模块编辑
     * @param className
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("{className}/modify")
    public JsonResponse modify(@PathVariable String className, HttpServletRequest request) {
        try {
            Map<String, Object> map = ApplicationUtils.getRequestDatas();
            /*
             *忽略属性，多个值用,号分隔如：menuName,menuIcon,menuOrder
             */
            String[] ignoreProperties = null;
            String ignore = request.getParameter("ignoreProperties");
            if(StringUtils.isNotBlank(ignore)){
                ignoreProperties = ignore.split(",");
                for(String temp: ignoreProperties){
                    map.remove(temp);
                }
            }
            Object oldVo = baseService.beanSpecification(className).selectById(map.get("id").toString());
            String oldJson = JSON.toJSONString(oldVo);
            @SuppressWarnings("unchecked")
            Map<String, Object> oldMap = JSON.parseObject(oldJson, Map.class);
            oldMap.putAll(map);
            String json = JSON.toJSONString(oldMap) ;
            Object newVo = JSON.parseObject(json, oldVo.getClass());
            baseService.beanSpecification(className).updateById(newVo);
            return JsonResponse.success();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return JsonResponse.error(CodeEnum.EX999);
        }
    }

    /**
     * 通用删除
     * @param className
     * @param id
     * @return
     */
    @RequestMapping("{className}/delete/{id}")
    @ResponseBody
    public JsonResponse deleteA(@PathVariable String className, @PathVariable String id) {
        try {
            baseService.beanSpecification(className).deleteById(id);
            return JsonResponse.success();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return JsonResponse.error(CodeEnum.EX999);
        }
    }

    /**
     * 查询附件
     */
    @ResponseBody
    @RequestMapping("/selectAtt")
    public JsonResponse selectAtt(){
        try {
            Map<String, Object> map = ApplicationUtils.getRequestDatas();
            String id = map.get("id").toString();
            Attachment attachment = attachmentMapper.selectById(id);
            return JsonResponse.success(attachment);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return JsonResponse.error(CodeEnum.EX999);
        }
    }

    /**
     * 通用删除，delete by id or grid rows
     * @param className
     */
    @RequestMapping("{className}/delete")
    @ResponseBody
    public JsonResponse deleteB(@PathVariable String className, HttpServletRequest request) {
        try {
            String id = request.getParameter("id");
            if (StringUtils.isNotBlank(id)) {
                String[] ids = id.split(",");
                List<String> idList= new ArrayList<>(Arrays.asList(ids));
                baseService.beanSpecification(className).deleteBatchIds(idList);
            }
            return JsonResponse.success();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return JsonResponse.error(CodeEnum.EX999);
        }
    }


    /**
     * layui通用上传
     */
    @ResponseBody
    @RequestMapping("/layui/upload")
    public JsonResponse layuiUpload(MultipartFile file){
        try {
            JSONObject attrs = new JSONObject();
            if (file.isEmpty()) {
                JsonResponse.error("文件为空");
            }else{
                // 获取文件名
                String original = file.getOriginalFilename();
                // 获取文件的后缀名
                String suffixName = original.substring(original.lastIndexOf("."));

                String newName = System.currentTimeMillis() + suffixName;
                String filePath = layuiUploadPath.concat(newName);

                File dest = new File(filePath);
                long size = file.getSize();

                // 检测是否存在目录
                if (!dest.getParentFile().exists()) {
                    dest.getParentFile().mkdirs();
                }
                file.transferTo(dest);
                User user = ApplicationUtils.getUser().getUser();
                if(dest.exists()){
                    Attachment att = new Attachment(newName,original,"成功",suffixName,filePath,size,user.getComId());
                    att.setCreaterId(user.getId());
                    baseService.beanSpecification(Attachment.class.getName()).insert(att);
                    attrs =(JSONObject) JSON.toJSON(att);
                }
            }
            return JsonResponse.success(attrs);
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            return JsonResponse.error("上传异常");
        }
    }

    /**
     * 文件下载
     */
    @RequestMapping("/download")
    public ResponseEntity<byte[]> downloadFile(String id,HttpServletRequest request) throws IOException {
        byte[] body = null;
        ResponseEntity<byte[]> response = null;
        Attachment attachment = attachmentMapper.selectById(id);
        if(attachment!=null){
            String filePath =  attachment.getUrl();
            String fileDisplay = attachment.getOriginal();

            FileSystemResource file = new FileSystemResource(filePath);
            if(!file.exists()){
                File createFile = new File(filePath);
                createFile.createNewFile();
                file = new FileSystemResource(filePath);
            }
            InputStream in = file.getInputStream();
            body = new byte[in.available()];
            in.read(body);

            String userAgent = request.getHeader("User-Agent");
            if(userAgent.contains("MSIE")||userAgent.contains("Trident")) {
                fileDisplay = java.net.URLEncoder.encode(fileDisplay, "UTF-8");
            }else {
                //非IE浏览器的处理：
                fileDisplay = new String(fileDisplay.getBytes("UTF-8"),"ISO-8859-1");
            }
            HttpHeaders headers = new HttpHeaders();
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Content-Disposition","attachment;filename=" + fileDisplay);
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");
            HttpStatus statusCode=HttpStatus.OK;
            response=new ResponseEntity<byte[]>(body,headers,statusCode);
        }else{

        }
        return response;
    }
}
